Øvelse 7

I øvelsen skal vi lære om implemetering af SPI - kommunikation i kernemoduler. Opgaven var at skrive en Driver til styring af en DAC - konverter.

Til at starte med fik vi udleveret et eksempel på en driver til en ADC7870, denne benytetde vi så som udgangspunkt til at skrive den nye driver,


Find ud af hvordan DAC7612 er forbundet til OMAP'en
Forbindelsen imellem DAC7612 og SPI1 er således at DAC7612 er forbundet til SPI1 og de benytter CS3 som bindeled og er aktiv lav.
connection2.PNG
spi.PNG

DAC7612's SPI karakteristika
Efter at dataen er kommet ind i shift registrert, kan disse data blive flyttet ind til DAC registret. Dette sker ved en HIGH to LOW transition af loaddacs pins. Denne pin gør DAC registret transperent.
Hvis så ny data bliver flyttet ind til shift registret imens at LOADDACS er lav vil output voltage skifte til for hvert nyt bit. For at undgå dette må vi sørge for at LOADDAG bliver retuneret

Opdeling af filerne.
  • DAC7612.c : Kerne modulet (init, exit, open, release, read og write funktioner)
  • DAC7612-core.c/h : implementering af driverfunktioner (skriver til devicet, sæser fra devicet, initiere devicet og opsætter devicet)
  • DAC7612-spi.c/h - SPI delen implementeres.
Filenerne benytter hinanden på den måde DAC7612.c kalder funktioner i DAC7612-core.c som så kalder funktioner i DAC7612-spi.c


A) implementere Init

INIT

I initfunktionen skal dette foretages.
  • Registrer major/minor numre osv.
  • Registre nye SPI-device til kernen
/*
*Information om DAC7612
*/
struct spi_board_info omap3devkit8000_spi_board_info[] = {
    {
     .modalias        = "dac7612",
     .bus_num         = 1,
     .chip_select     = 3,
     .max_speed_hz    = 15000000,
     .controller_data = &dac7612_mcspi_config,
     .mode            = SPI_MODE_3,//clock
    }
};
Vi ønsker at sætte bits_per_word til 8 da vi skal sende 8 bit af gangen.
/*
*Byte aligning
*/
spi -> bits_per_word = 8;
spi_setup(spi);
retuen 0;
 
b)
For at teste denne den satte vi en fast værdi i vores init og checkede at vi fik en spænding der svarede til værdien.

c)
I core filen laver vi en write funktion, denne tager to argumenter. Reg. som fortæller om det et Register A eller B, og så en værdi vi vil skrive.
Når vi gør dette behøver vores char device ikke at have noget kendskab til SPI.

int dac7612_write(u16 reg, u16 val)
{
 return dac7612_spi_write(dac7612_spi_device,reg,val);
}
Da vi skulle finde Chipselected samt busnumre gik vi ind på hjemmesiden
http://devkit8000addon.wikispaces.com/Schematic hvor de var opgivet. Ud fra denne side kunne vi i skemaet se at vi skulle benytte CS3 og Spi1.

Spi write funktionen

Fra start fik vi som nænvt tidligere udleveret en driver til ADC7870, denne kunne vi benytte under tæsten af vores egen driver.
Under testen indsatte vi ADC7870 og vores egen DAC7612. Herefter oprettede vi node til begge og forbandt dem. Udgangen blev forbundet til DAC og indgangen til ADC.
På denne måde kunne vi skrive en værdi til DAC og læse den på ADC.

Ved hjælp af et multimeter kontrolerede vi igen og så at den sendte og at det som den sendte også kom ud på pinden.
#define REGA 0x02
#define REGB 0x03
 
/*
 * Write to the SPI DAC
 */
int dac7612_spi_write(struct spi_device *spi, u16 reg, u16 val)
{
    u8 data[2];
 
    /*
     * Init message
     */
    struct spi_message msg;
    struct spi_transfer transfer;
 
    /*
     * Format
     * A1,A0,<DATA>
     */
    if(reg) {
        data[0] = REGB << 4 | ( (val >> 8) & 0x0f);
    } else {
        data[0] = REGA << 4 | ( (val >> 8) & 0x0f);
    }
 
    /*
     * Low 8bit
     */
    data[1] = val & 0xff;
 
    memset(&transfer,0,sizeof(transfer));
    spi_message_init(&msg);
    msg.spi=spi;
 
    transfer.tx_buf = data;
    transfer.rx_buf = NULL;
    transfer.len = 2;
 
    /*
     * Add message to queue
     */
    spi_message_add_tail(&transfer, &msg);
 
    spi_sync(msg.spi,&msg);
 
}